using System.Data;
using System.Xml.Serialization;

namespace ODX.Core
{
    /// <summary>
    /// Each database provides it's own way of sorting null values.
    /// MS SQL, MS Access put nulls at the top of a query result assuming null is minimum value.
    /// ORACLE, PostgreSQL put null at bottom of a query result assuming null is maximum value.
    /// </summary>
    public enum NullsPosition
    {
        /// <summary>Default value. Should not be used directly.</summary>
        Undefined,

        /// <summary>Nulls are maxinum values</summary>
        Minimum,

        /// <summary>Nulls are minimum values</summary>
        Maximum
    }

    [XmlType(Namespace = "http://codeplex.com/odx")]
    /// <summary>
    /// Defines cuncurrency pattern to use when saving data to a data source.
    /// </summary>
    public enum SaveMode
    {
        /// <summary>Changes are sent to the data source and concurent changes are checked. ODX checker is used. Unique constraints handled correctly.</summary>
        Concurrent,

        /// <summary>Changes are sent to the data source and no concurency check is performed.</summary>
        Overwrite,

        /// <summary>Complete client DataSet is sent to the data source. No concurency check is performed.</summary>
        Complete
    }

    /// <summary>
    /// Interface to a data source used by session to restrieve/save data.
    /// </summary>
    public interface IDataProvider
    {
        /// <summary>
        /// Selects records from a data source using specified filter sort order.
        /// </summary>
        /// <param name="tableName">Table name in data source to be queried.</param>
        /// <param name="filter">Filter expression to be applied to the table. '?' marks are accepted as parameters placeholders</param>
        /// <param name="sort">List of sort fields.</param>
        /// <param name="count">Nubler of records to be queried.</param>
        /// <param name="parameters">Parameters to be used instead '?' in filter expression.</param>
        /// <returns>DataSet contained queried data and optionally prefetched records.</returns>
        DataSet Select(string tableName, string filter, string sort, int count, params object[] parameters);

        /// <summary>
        /// Queries single record from a data source.
        /// </summary>
        /// <param name="tableName">Table name in data source to be queried.</param>
        /// <param name="ID">ID of a record to be returned.</param>
        /// <returns>DataSet contained the requested record and optionally prefetched records.</returns>
        DataSet GetRecord(string tableName, string ID);

        /// <summary>
        /// Returns complete list of child records for the specified parent record.
        /// </summary>
        /// <param name="childTableName">Name of child table.</param>
        /// <param name="childFK">Name of FK field in child table.</param>
        /// <param name="parentID">ID of parent record.</param>
        /// <returns>DataSet contained child records and optionally prefetched records.</returns>
        DataSet GetChildren(string childTableName, string childFK, string parentID);

        /// <summary>
        /// Returns records linked N:M to the specified parent record.
        /// </summary>
        /// <param name="linkTableName">Link table name.</param>
        /// <param name="childTableName">Name of table to query child records</param>
        /// <param name="parentFK">Name of fielf in link table that is FK to the parent table.</param>
        /// <param name="childFK">Name of fielf in link table that is FK to the child table.</param>
        /// <param name="parentID">ID of parent record.</param>
        /// <returns>DataSet contained child records and optionally prefetched records</returns>
        DataSet GetAssoc(string linkTableName, string childTableName, string parentFK, string childFK, string parentID);

        /// <summary>
        /// Saves DataSet to the underlying data source
        /// </summary>
        /// <param name="changes">DataSet, typically contained changes made by user or algorithms.</param>
        /// <param name="saveMode">Concurrent changes processing rules.</param>
        void Save(DataSet changes, SaveMode saveMode);

        /// <summary>
        /// Defines positions of nulls in ordered data. 
        /// </summary>
        NullsPosition NullsPosition { get; }
    }

    /// <summary>
    /// Data provider interface for the data sources that support SQL queries
    /// </summary>
    public interface ISqlDataProvider : IDataProvider
    {
        /// <summary>
        /// Selects records from a data source using specified SQL statement.
        /// </summary>
        /// <param name="selectSql">SQL SELECT statement.</param>
        /// <param name="tableName">Table name to put results into.</param>
        /// <param name="count">Number of records to be retrieved from the data source.</param>
        /// <param name="parameters">Parameters to be used instead '?' marks in sql statement.</param>
        /// <returns>DataSet contained queried data and optionally prefetchd records.</returns>
        DataSet SelectSql(string selectSql, string tableName, int count, params object[] parameters);
    }
}
